 /**
 * 逻辑、功能相关描述: <br>
 *
 * @author 付湘辉  <br>
 * 编写日期：2008-12-24  <br>
 */
package com.ce.pms.charge.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.util.Assert;
import com.ce.pms.base.service.impl.PmsBaseServiceImpl;
import com.ce.pms.charge.dao.IChargeRecordDao;
import com.ce.pms.charge.model.BusinessCodeDomain;
import com.ce.pms.charge.model.ChargeRecordDO;
import com.ce.pms.charge.service.IBusinessCodeService;
import com.ce.pms.charge.service.IChargeRecordProcessor;
import com.ce.pms.charge.service.INonConventionalChargeService;
import com.ce.pms.charge.vo.ChargeRecordVO;
import com.ce.pms.common.model.SysInfo;
import com.ce.pms.common.model.SysrefcodeDO;
import com.ce.pms.common.service.ISecUserService;
import com.ce.pms.common.util.StringAnalysiUtil;
import com.ce.pms.custservice.dao.IBillDao;
import com.ce.pms.custservice.model.BillDO;
import com.ce.pms.exception.BusinessException;
import com.ce.pms.house.model.HouseDomain;
import com.ce.pms.house.service.IHouseService;
import com.ce.util.BeanUtil;
import com.ce.util.BlankUtil;

/**
 * 	名称: com.ce.pms.charge.service.impl.NonConventionalChargeServiceImpl <br>
 * 非常规费用业务实现
 *
 * @author  付湘辉(开发) ，马思权(设计) <br>
 * Created on： 2008-12-24 <br>
 * @author <br>
 * update on： <br>
 * why: <br>
 */
public class NonConventionalChargeServiceImpl extends PmsBaseServiceImpl implements INonConventionalChargeService{

	private IBillDao billDao;

	private IChargeRecordDao chargeRecordDao;

	private Map<String, IChargeRecordProcessor> chargeRecordProcessors;

	private IHouseService houseService;

	   /**
	   * 功能描述: 新增一笔费用记录 <br>
	   * @param chargeRecord
	   * @return com.ce.pms.renovation.vo.ChargeRecordVO
	   *
	   * Create author:付湘辉 <br>
	   * Create on:2008-12-24  <br>
	   * Edit author:  <br>
	   * Edit on:    <br>
	   * Why:     <br>
	   */
		public ChargeRecordVO addChargeRecord(ChargeRecordVO chargeRecord) {
			Assert.notNull(chargeRecord);
			ChargeRecordDO chargeRecordDO = new ChargeRecordDO();
			SysInfo sysInfo = super.createInfo(chargeRecord.getCreator());
			chargeRecord.setSysDate(sysInfo.getSysDate());
			chargeRecordDO.setSysInfo(sysInfo);
			//装配
			this.assembleChargeRecordV2D(chargeRecord, chargeRecordDO);

			//检查必须项
			chargeRecordDO.checkRequiredField();
			this.chargeRecordDao.saveObject(chargeRecordDO);

			return chargeRecord;
		}

	/**
	    * 功能描述: 删除费用记录 <br>
	    * @param chargeRecordId - 费用记录Id
	    * @roseuid 4945FAE90399
	    * @return Boolean
	    *
	    * Create author:付湘辉 <br>
	    * Create on:2008-12-24  <br>
	    * Edit author:  <br>
	    * Edit on:    <br>
	    * Why:     <br>
	    */
	public Boolean deleteChargeRecord(Long chargeRecordId) {
		Assert.notNull(chargeRecordId);
		ChargeRecordDO chargeRecordDO = this.chargeRecordDao.findById(chargeRecordId);
		if (SysrefcodeDO.CONSTANTS_DIGITAL_ONE.equals(chargeRecordDO.getHandleYn())) {
			throw new BusinessException("charge:charge_cannot_delete_the_handlerecord_exception",
					BusinessException.WARNING);
		}
		ChargeRecordVO chargeRecordVO = new ChargeRecordVO();
		this.assembleChargeRecordD2V(chargeRecordDO, chargeRecordVO);
		IChargeRecordProcessor process = this.getChargeRecordProcessor(chargeRecordDO.getBizModule());
		this.chargeRecordDao.deleteObject(chargeRecordDO);
		return process.deleteChargeRecord(chargeRecordVO);
	}

   /**
	 * 功能描述:删除未处理的费用记录<br>
	 * @param bizModule
	 * @param bizType
	 * @param bizId<br>
	 * Create author:罗军林<br>
	 * Create on:2008-12-25<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	public Boolean deleteChargeRecordByBiz(String bizModule,String bizType,Long bizId){
		Boolean res = this.chargeRecordDao.deleteChargeRecordByBiz(bizModule, bizType, bizId);
		return res;
	}

	/**
	    * 功能描述:修改费用记录  <br>
	    * @param chargeRecord - 费用记录VO
	    * @roseuid 4945FA700119
	    * @return ChargeRecordVO
	    *
	    * Create author:付湘辉 <br>
	    * Create on:2008-12-24  <br>
	    * Edit author:  <br>
	    * Edit on:    <br>
	    * Why:  <br>
	    */
		public ChargeRecordVO editChargeRecord(ChargeRecordVO chargeRecord) {
			Assert.notNull(chargeRecord);
			IChargeRecordProcessor process = this.getChargeRecordProcessor(chargeRecord.getBizModule());
			return process.editChargeRecord(chargeRecord);
		}

	/**
	 * 功能描述: 批量修改费用记录 <br>
	 * @param operator 操作者ID
	 * @param chargeRecordVos 费用记录数据集
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-12-26  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	public List<ChargeRecordVO> editChargeRecordBatch(Long operator,List<ChargeRecordVO> chargeRecordVos){
		Assert.notNull(chargeRecordVos);
		Map<String, List<ChargeRecordVO>> map = this.sortChargeRecords(chargeRecordVos);
		Set<String>  set = map.keySet();
		List<ChargeRecordVO> resList = new ArrayList<ChargeRecordVO>();
		for (String str : set) {
			IChargeRecordProcessor  crp = this.getChargeRecordProcessor(str);
			resList.addAll(crp.editChargeRecordBatch(operator, map.get(str)));//调用处理器接口
		}
		return resList;
	}



	/**
	    * 功能描述:根据房间ID获得没处理的费用记录  <br>
	    * 根据房间ID获得没处理的费用记录
	    * @param houseId - 房屋ID
	    * @return List
	    * @roseuid 4945E90C0213
	    *
	    * Create author:付湘辉 <br>
	    * Create on:2008-12-24  <br>
	    * Edit author:  <br>
	    * Edit on:    <br>
	    * Why:     <br>
	    */
	public List<ChargeRecordVO> getUnHandleChargeRecords(Long houseId) {
		Assert.notNull(houseId);
		List<Long> tempList = this.houseService.queryHouseIdListById(houseId);

		//得到一个由多个产权房ID拼接而成的字符串，使用逗号分隔
		String houseIds = StringAnalysiUtil.portfolioFormattedString(tempList);
		//Dao查询
		List<ChargeRecordDO> list = this.chargeRecordDao.getUnHandleChargeRecords(houseIds);

		List<ChargeRecordVO> resList = new ArrayList<ChargeRecordVO>();
		synchronized (this) {
			this.initHmployeeNameCache();
			for (Iterator<ChargeRecordDO> iter = list.iterator(); iter.hasNext();) {
				ChargeRecordDO element = iter.next();
				ChargeRecordVO chargeRecordVO = new ChargeRecordVO();
				resList.add(this.assembleChargeRecordD2V(element,chargeRecordVO));
				if (chargeRecordVO.getCreator() != null) {
					// 操作人名称
					if (this.hmployeeNameCacheMap.get(chargeRecordVO.getCreator())==null) {
						this.hmployeeNameCacheMap.put(chargeRecordVO.getCreator(), this.secUserService.queryUserNameById(chargeRecordVO.getCreator()));
					}
					chargeRecordVO.setOperatorName(this.hmployeeNameCacheMap.get(chargeRecordVO.getCreator()));
				}
			}
			this.destoreMapCache();
		}
		return resList;
	}

	/**
	    * 功能描述:处理费用记录  <br>
	    * @param accountHouseId 房屋ID
	    * @param operator 操作者
	    * @param businessCodeId - 支付交易码ID
	    * @param chargeRecords - 费用记录集
	    * @roseuid 4945E9B200AB
	    * @return Boolean
	    *
	    * Create author:付湘辉 <br>
	    * Create on:2008-12-24  <br>
	    * Edit author:  <br>
	    * Edit on:    <br>
	    * Why:     <br>
	    */
	public Boolean handleChargeRecords(Long accountHouseId, Long operator, Long businessCodeId, List<ChargeRecordVO> chargeRecords) {
		super.checkParameterIsNull("common:parameters_null_exception, ", accountHouseId,operator,businessCodeId,chargeRecords);
		//检查是否含有已处理记录
		checkIsAllowHandle(chargeRecords);
		List<Long> chargeRecordIds = new ArrayList<Long>();
		for (ChargeRecordVO recordVO : chargeRecords) {
			chargeRecordIds.add(recordVO.getKeyword());
			recordVO.setHandleYn(SysrefcodeDO.CONSTANTS_DIGITAL_ONE);
		}
		// 批量改变成已处理状态
		this.chargeRecordDao.updateChargeRecordHandleStatusToYes(chargeRecordIds, operator, super.getDate());
		//分类记录
		Map<String, List<ChargeRecordVO>> map = this.sortChargeRecords(chargeRecords);
		Set<String>  set = map.keySet();

		for (String str : set) {
			IChargeRecordProcessor  crp = this.getChargeRecordProcessor(str);
			crp.handleChargeRecords(accountHouseId, operator, businessCodeId, map.get(str));//调用处理器接口
		}

		return true;
	}

	/** 功能描述:  <br>
	 * @param chargeRecords
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-12  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private void checkIsAllowHandle(List<ChargeRecordVO> chargeRecords) {
		Boolean  isAllow  = this.isAllowHandle(chargeRecords);
		if (!isAllow) {
			throw new BusinessException("charge:charge_not_allowhandle_record_is_yes_exception",
					BusinessException.WARNING);
		}
	}

	/**
	    * 功能描述: 月末结算 <br>
	    * @param chargeRecordVO
	    *
	    * Create author:付湘辉 <br>
	    * Create on:2008-12-24  <br>
	    * Edit author:  <br>
	    * Edit on:    <br>
	    * Why:     <br>
	    */
	   public ChargeRecordVO monthBalance(ChargeRecordVO chargeRecordVO){
		   Assert.notNull(chargeRecordVO);
		   //判断业务模块类型
		   this.checkIsSERBizMoudle(chargeRecordVO);
		   //检查是否已处理
		   this.checkIsAllowHandle(Arrays.asList(new ChargeRecordVO[]{chargeRecordVO}));

		   //检查是否是月末结算模式
		   checkIsMonthBalance(chargeRecordVO);
		   
		   // 处理单个费用记录
		   this.handleSingleRecord(chargeRecordVO);
		   
		   //用其费用处理器进行月末结算业务
		   IChargeRecordProcessor process = this.getChargeRecordProcessor(chargeRecordVO.getBizModule());
		   chargeRecordVO = process.monthBalance(chargeRecordVO);
		   return chargeRecordVO;
	   }

	/** 功能描述:  <br>
	 * @param chargeRecordVO
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-12  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private void checkIsSERBizMoudle(ChargeRecordVO chargeRecordVO) {
		if (!SysrefcodeDO.FEE_CHARGE_RECORD_BIZ_MOUDLE_SER.equals(chargeRecordVO.getBizModule())) {
			   throw new BusinessException("charge:charge_not_customerservice_mode_exception",
						BusinessException.WARNING);
		   }
	}

	/** 功能描述:  <br>
	 * @param chargeRecordVO
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2009-1-12  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	*/
	private void checkIsMonthBalance(ChargeRecordVO chargeRecordVO) {
		BillDO bill = this.billDao.findById(chargeRecordVO.getBizId());
		   if (!bill.isMonthBalance()) {
			   throw new BusinessException("charge:charge_not_month_balance_exception",
						BusinessException.WARNING);
		   }
	}

	   /**
		 * 功能描述: 查询指定业务模块，类型，ID的费用记录 <br>
		 * @param bizModule
		 * @param bizType
		 * @param bizId
		 * @return
		 *
		 * Create author:付湘辉 <br>
		 * Create on:2009-1-5  <br>
		 * Edit author:  <br>
		 * Edit on:    <br>
		 * Why:     <br>
		 */
		public ChargeRecordVO getChargeRecordByBiz(String bizModule,String bizType,Long bizId){
			Assert.notNull(bizModule);
			Assert.notNull(bizType);
			Assert.notNull(bizId);
			ChargeRecordDO chargeRecordDO = this.chargeRecordDao.getChargeRecordByBiz(bizModule, bizType, bizId);
			if(BlankUtil.isBlank(chargeRecordDO)) return null;
			ChargeRecordVO chargeRecordVO = new ChargeRecordVO();
			this.assembleChargeRecordD2V(chargeRecordDO, chargeRecordVO);
			return chargeRecordVO;
		}

	   /**
	 * @param billDao the billDao to set
	 */
	public void setBillDao(IBillDao billDao) {
		this.billDao = billDao;
	}
	/**
	 * @param chargeRecordDao the chargeRecordDao to set
	 */
	public void setChargeRecordDao(IChargeRecordDao chargeRecordDao) {
		this.chargeRecordDao = chargeRecordDao;
	}

	/**
	 * @param chargeRecordProcessors the chargeRecordProcessors to set
	 */
	public void setChargeRecordProcessors(
			Map<String, IChargeRecordProcessor> chargeRecordProcessors) {
		this.chargeRecordProcessors = chargeRecordProcessors;
	}

	/**
	 * @param houseService the houseService to set
	 */
	public void setHouseService(IHouseService houseService) {
		this.houseService = houseService;
	}

	/**
	 * 员工姓名缓冲，以用户id为key,员工姓名为value
	 */
   @SuppressWarnings("unused")
   private Map<Long, String> hmployeeNameCacheMap;

   private void initHmployeeNameCache(){
	   hmployeeNameCacheMap=new HashMap<Long, String>();
   }

   private void destoreMapCache(){
		this.hmployeeNameCacheMap = null;
  }

	/**
	 * 功能描述:费用记录DO2VO  <br>
	 * @param chargeRecordDO
	 * @param chargeRecordVO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-12-24  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private ChargeRecordVO assembleChargeRecordD2V(ChargeRecordDO chargeRecordDO,ChargeRecordVO chargeRecordVO){
		BeanUtil.convertVoAsDo(chargeRecordDO,chargeRecordVO);

		HouseDomain house = chargeRecordDO.getHouse();
		if (!BlankUtil.isBlank(house)) {
			chargeRecordVO.setHouseId(house.getKeyword());
			chargeRecordVO.setHouseNumber(house.getHouseNumber());
		}

		BusinessCodeDomain businessCodeDo = chargeRecordDO.getBizCode();
		if (!BlankUtil.isBlank(businessCodeDo)) {
			chargeRecordVO.setBusinessId(businessCodeDo.getKeyword());
			chargeRecordVO.setBizCode(businessCodeDo.getBizCode());
		}

		SysInfo sysInfo = chargeRecordDO.getSysInfo();
		if (!BlankUtil.isBlank(sysInfo)) {
			BeanUtil.convertVoAsDo(sysInfo,chargeRecordVO);
		}

		return chargeRecordVO;
	}
	/**
	 * 用户Service
	 */
	private ISecUserService secUserService;
	/**
	 * 交易码Service
	 */
	private IBusinessCodeService businessCodeService;

	/**
	 * 功能描述:费用记录VO2DO  <br>
	 * @param chargeRecordVO
	 * @param chargeRecordDO
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-12-24  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private ChargeRecordDO assembleChargeRecordV2D(ChargeRecordVO chargeRecordVO,ChargeRecordDO chargeRecordDO){

		BeanUtil.convertVoAsDo(chargeRecordVO,chargeRecordDO);
		//房屋
		if (!BlankUtil.isBlank(chargeRecordVO.getHouseId())) {
			HouseDomain house = this.houseService.getHouseById(chargeRecordVO.getHouseId());
			chargeRecordDO.setHouse(house);
		}

		//交易码
		if (!BlankUtil.isBlank(chargeRecordVO.getBusinessId())) {
			BusinessCodeDomain bizCode = this.businessCodeService.getBusinessCodeDomainById(chargeRecordVO.getBusinessId());
			chargeRecordDO.setBizCode(bizCode);
		}

		return chargeRecordDO;
	}

	/**
	 * 功能描述:修改一条费用记录 <br>
	 * @param chargeRecord
	 * @param sysInfo
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-12-26  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private ChargeRecordVO editChargeRecordInner(ChargeRecordVO chargeRecord,SysInfo sysInfo) {
		ChargeRecordDO chargeRecordDO = this.chargeRecordDao.findById(chargeRecord.getKeyword());
		this.assembleChargeRecordV2D(chargeRecord, chargeRecordDO);
		BeanUtil.convertVoAsDo(sysInfo, chargeRecordDO.getSysInfo());
		chargeRecordDO.checkRequiredField();
		this.chargeRecordDao.updateObject(chargeRecordDO);
		return chargeRecord;
	}

	/**
	 * 功能描述:根据模块码获得费用处理器  <br>
	 * @param bizModule 模块码
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-12-24  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private IChargeRecordProcessor getChargeRecordProcessor(String bizModule)	{
		return this.chargeRecordProcessors.get(bizModule);
	}

	/**
	 * 功能描述: 处理单个费用记录 <br>
	 *
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-12-24  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private void handleSingleRecord(ChargeRecordVO chargeRecordVO) {
		SysInfo sysInfo = new SysInfo();
		sysInfo.setModifier(chargeRecordVO.getModifier());
		sysInfo.setModifyDate(super.getDate());
		chargeRecordVO.setHandleYn(SysrefcodeDO.CONSTANTS_DIGITAL_ONE);
		this.editChargeRecordInner(chargeRecordVO, sysInfo);
	}

	/**
	 * 功能描述:是否允许处理  <br>
	 * @param chargeRecords 费用记录列表
	 * @return
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-12-24  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private Boolean isAllowHandle(List<ChargeRecordVO> chargeRecords) {
		Assert.notNull(chargeRecords);
		for (ChargeRecordVO recordVO : chargeRecords) {
			if (SysrefcodeDO.CONSTANTS_DIGITAL_ONE.equals(recordVO.getHandleYn())) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 功能描述:按模块分类费用记录  <br>
	 * @param  chargeRecords 费用记录VO列表
	 *
	 *
	 * Create author:付湘辉 <br>
	 * Create on:2008-12-24  <br>
	 * Edit author:  <br>
	 * Edit on:    <br>
	 * Why:     <br>
	 */
	private Map<String, List<ChargeRecordVO>> sortChargeRecords(List<ChargeRecordVO> chargeRecords) {
		Map<String, List<ChargeRecordVO>> map = new HashMap<String, List<ChargeRecordVO>>();
		for (ChargeRecordVO recordVO : chargeRecords) {
			if (map.get(recordVO.getBizModule())==null) {
				map.put(recordVO.getBizModule(), new ArrayList<ChargeRecordVO>());
			}
			map.get(recordVO.getBizModule()).add(recordVO);
		}
		return map;
	}

	/**
	 * 功能描述: 检查某项费用的所有未入账费用记录是否都已经处理<br>
	 * @param bizModule
	 * @param bizType
	 * @param bizIds
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2009-1-8<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	public Boolean checkFinishHandleYn(String bizModule, String bizType, List<Long> bizIds) {
		return chargeRecordDao.checkFinishHandleYn(bizModule, bizType, bizIds);
	}

	/**
	 * 功能描述: 检查某项费用的所有未入账费用记录是否都未处理 <br>
	 * 只要有一项已经处理，都将返回false
	 * @param bizModule
	 * @param bizType
	 * @param bizIds
	 * @return<br>
	 * Create author:罗军林<br>
	 * Create on:2009-1-8<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	public Boolean checkFinishIsHandle(String bizModule, String bizType, List<Long> bizIds) {
		return chargeRecordDao.checkFinishIsHandle(bizModule, bizType, bizIds);
	}



	public void setSecUserService(ISecUserService secUserService) {
		this.secUserService = secUserService;
	}

	/**
	 * @param businessCodeService the businessCodeService to set
	 */
	public void setBusinessCodeService(IBusinessCodeService businessCodeService) {
		this.businessCodeService = businessCodeService;
	}


}
